bitkeeper revision 1.3 (3ddba75cRdjLs2ie8aQo_VuXG8i-Kw)
authorakw27@boulderdash.cl.cam.ac.uk <akw27@boulderdash.cl.cam.ac.uk>
Wed, 20 Nov 2002 15:16:44 +0000 (15:16 +0000)
committerakw27@boulderdash.cl.cam.ac.uk <akw27@boulderdash.cl.cam.ac.uk>
Wed, 20 Nov 2002 15:16:44 +0000 (15:16 +0000)
Dom0 proc interface to vfr rules.
Rules stored in liked list in kernel.
Vif lookup table.

.rootkeys
BitKeeper/etc/logging_ok
xen-2.4.16/common/network.c
xen-2.4.16/include/hypervisor-ifs/network.h
xen-2.4.16/include/xeno/vif.h
xen-2.4.16/net/dev.c
xenolinux-2.4.16-sparse/arch/xeno/drivers/dom0/Makefile
xenolinux-2.4.16-sparse/arch/xeno/drivers/dom0/vfr.c [new file with mode: 0644]
xenolinux-2.4.16-sparse/include/asm-xeno/hypervisor-ifs/network.h

index 1544186af7ab34fe54663916ca4f017f04b5dad1..feb26f56e2f6021ab640af50dc085000d13da64e 100644 (file)
--- a/.rootkeys
+++ b/.rootkeys
 3ddb79b75eo4PRXkT6Th9popt_SJhg xenolinux-2.4.16-sparse/arch/xeno/drivers/dom0/Makefile
 3ddb79b7Xyaoep6U0kLvx6Kx7OauDw xenolinux-2.4.16-sparse/arch/xeno/drivers/dom0/dom0_core.c
 3ddb79b7PulSkF9m3c7K5MkxHRf4hA xenolinux-2.4.16-sparse/arch/xeno/drivers/dom0/dom0_ops.h
+3ddba759XOjcl_OF-52dOYq7sgMykQ xenolinux-2.4.16-sparse/arch/xeno/drivers/dom0/vfr.c
 3ddb79b7s7yYBioHidSkIoHtQxYmOw xenolinux-2.4.16-sparse/arch/xeno/drivers/network/Makefile
 3ddb79b7CpLL98ScdpbKkVBktlbCtQ xenolinux-2.4.16-sparse/arch/xeno/drivers/network/network.c
 3ddb79b7hqi9krq6h98lnpONHGzvEA xenolinux-2.4.16-sparse/arch/xeno/kernel/Makefile
index d8aa55ca1f21461b1230adeb49ea1a8648188a3e..05edeace5b85161e076f361bb16ee6276406d56a 100644 (file)
@@ -1 +1,2 @@
+akw27@boulderdash.cl.cam.ac.uk
 smh22@boulderdash.cl.cam.ac.uk
index 7fc7b99370c8c1185f4ce630ac9887d9169156fe..e64c740f45d78d220cf584be7607f2999fa98fbf 100644 (file)
 #include <xeno/errno.h>
 #include <xeno/init.h>
 #include <xeno/slab.h>
+#include <xeno/spinlock.h>
+
+/* vif globals 
+ * sys_vif_list is a lookup table for vifs, used in packet forwarding.
+ * it should be replaced later by something a little more flexible.
+ */
 
-/* vif globals */
 int sys_vif_count;
+net_vif_t *sys_vif_list[MAX_SYSTEM_VIFS];
+net_rule_ent_t *net_rule_list;
 kmem_cache_t *net_vif_cache;
+kmem_cache_t *net_rule_cache;
+static rwlock_t net_rule_lock = RW_LOCK_UNLOCKED;
 
 net_ring_t *create_net_vif(int domain)
 {
@@ -63,6 +72,84 @@ void destroy_net_vif(struct task_struct *p)
 }
 
 
+int add_net_rule(net_rule_t *rule)
+{
+    net_rule_ent_t *new_ent;
+    
+    if ( (new_ent = kmem_cache_alloc(net_rule_cache, GFP_KERNEL)) == NULL )
+    {
+        return -ENOMEM;
+    }
+
+    memcpy(&new_ent->r, rule, sizeof(net_rule_t));
+
+    write_lock(&net_rule_lock);
+    new_ent->next = net_rule_list;
+    net_rule_list = new_ent;
+    write_unlock(&net_rule_lock);
+
+    return 0;
+}
+
+int delete_net_rule(net_rule_t *rule)
+{
+    net_rule_ent_t *ent = net_rule_list, *prev = NULL;
+
+    while ( (ent) && (!(memcmp(rule, &ent->r, sizeof(net_rule_t)))) )
+    {
+        prev = ent;
+        ent = ent->next;
+    }
+
+    if (ent)
+    {
+        write_lock(&net_rule_lock);
+        if (prev)
+        {
+            prev->next = ent->next;
+        }
+        else
+        {
+            net_rule_list = ent->next;
+        }
+        kmem_cache_free(net_rule_cache, ent);
+        write_unlock(&net_rule_lock);
+    }
+
+    return 0;
+}
+        
+void print_net_rule(net_rule_t *r)
+{
+    printk("===] NET RULE:\n");
+    printk("=] src_addr         : %lu\n", (unsigned long) r->src_addr);
+    printk("=] src_addr_mask    : %lu\n", (unsigned long) r->src_addr_mask);   
+    printk("=] dst_addr         : %lu\n", (unsigned long) r->dst_addr);
+    printk("=] dst_addr_mask    : %lu\n", (unsigned long) r->dst_addr_mask);
+    printk("=] src_port         : %u\n", r->src_port);
+    printk("=] src_port_mask    : %u\n", r->src_port_mask);
+    printk("=] dst_port         : %u\n", r->dst_port);
+    printk("=] dst_port_mask    : %u\n", r->dst_port_mask);
+    printk("=] dst_proto        : %u\n", r->proto);
+    printk("=] src_interface    : %u\n", r->src_interface);
+    printk("=] dst_interface    : %u\n", r->dst_interface);
+    printk("=] action           : %u\n", r->action);
+}
+
+void print_net_rule_list()
+{
+    net_rule_ent_t *ent = net_rule_list;
+    int count = 0;
+    
+    while (ent) 
+    {
+        print_net_rule(&ent->r);
+        ent = ent->next;
+        count++;
+    }
+    printk("\nTotal of %d rules.\n", count);
+}
+
 /* 
  * This is the hook function to handle guest-invoked traps requesting 
  * changes to the network system.
@@ -78,22 +165,30 @@ long do_network_op(network_op_t *u_network_op)
 
     if ( copy_from_user(&op, u_network_op, sizeof(op)) )
         return -EFAULT;
-
     switch ( op.cmd )
     {
 
     case NETWORK_OP_ADDRULE:
     {
-        printk("received addrule request from guestos!\n");
+        add_net_rule(&op.u.net_rule);
     }
     break;
 
     case NETWORK_OP_DELETERULE:
     {
-        printk("received deleterule request from guestos!\n");
+        delete_net_rule(&op.u.net_rule);
     }
     break;
 
+    case NETWORK_OP_GETRULELIST:
+    {
+        // This should eventually ship a rule list up to the VM
+        // to be printed in its procfs.  For now, we just print the rules.
+        
+        print_net_rule_list();
+    }
+    break;
+    
     default:
         ret = -ENOSYS;
     }
@@ -104,6 +199,9 @@ long do_network_op(network_op_t *u_network_op)
 void __init net_init (void)
 {
     sys_vif_count = 0;
+    net_rule_list = NULL;
     net_vif_cache = kmem_cache_create("net_vif_cache", sizeof(net_vif_t),
-                                      0, SLAB_HWCACHE_ALIGN, NULL, NULL);
+                                    0, SLAB_HWCACHE_ALIGN, NULL, NULL);
+    net_rule_cache = kmem_cache_create("net_rule_cache", sizeof(net_rule_ent_t),
+                                    0, SLAB_HWCACHE_ALIGN, NULL, NULL);
 }
index 30a5bf34148c0617f079a26f77a1cd8534aebbc9..54cb99095a1b6922d17f4dd466de81c6da57c815 100644 (file)
@@ -51,22 +51,19 @@ typedef struct net_ring_st {
     unsigned int rx_ring_size;
 } net_ring_t;
 
-/* This is here for consideration:  Having a global lookup for vifs
- * may make the guest /proc stuff more straight forward, and could 
- * be used in the routing code.  I don't know if it warrants the 
- * overhead yet.
- */
-
-/* net_vif_t sys_vif_list[MAX_SYSTEM_VIFS]; */
-
 /* Specify base of per-domain array. Get returned free slot in the array. */
 net_ring_t *create_net_vif(int domain);
 
 /* Packet routing/filtering code follows:
  */
 
-#define NETWORK_ACTION_DROP 0
-#define NETWORK_ACTION_PASS 1
+#define NETWORK_ACTION_ACCEPT   0
+#define NETWORK_ACTION_COUNT    1
+
+#define NETWORK_PROTO_IP        0
+#define NETWORK_PROTO_TCP       1
+#define NETWORK_PROTO_UDP       2
+#define NETWORK_PROTO_ARP       3
 
 typedef struct net_rule_st 
 {
@@ -78,10 +75,11 @@ typedef struct net_rule_st
     u32  dst_addr_mask;
     u16  src_port_mask;
     u16  dst_port_mask;
-
-    int  src_interface;
-    int  dst_interface;
-    int  action;
+    u16  proto;
+    
+    u16  src_interface;
+    u16 dst_interface;
+    u16  action;
 } net_rule_t;
 
 /* Network trap operations and associated structure. 
@@ -91,6 +89,7 @@ typedef struct net_rule_st
 
 #define NETWORK_OP_ADDRULE      0
 #define NETWORK_OP_DELETERULE   1
+#define NETWORK_OP_GETRULELIST  2
 
 typedef struct network_op_st 
 {
@@ -101,7 +100,13 @@ typedef struct network_op_st
     }
     u;
 } network_op_t;
-    
+
+typedef struct net_rule_ent_st
+{
+    net_rule_t r;
+    struct net_rule_ent_st *next;
+} net_rule_ent_t;
+
 /* Drop a new rule down to the network tables. */
 int add_net_rule(net_rule_t *rule);
 
index 3ef0f1f9919c4de268f3265923ce67a49c11152a..6c1a1807a553c07b1f18862776e6056c16590144 100644 (file)
@@ -29,6 +29,7 @@ typedef struct net_vif_st {
 
 /* vif globals */
 extern int sys_vif_count;
+extern net_vif_t *sys_vif_list[];
 
 /* vif prototypes */
 net_ring_t *create_net_vif(int domain);
index 160aedc19157b6fac334d42e8b0beecf843b3849..dd376df98d5e279a4913e89d809aba5627e0e129 100644 (file)
@@ -1912,72 +1912,75 @@ long do_net_update(void)
 {
     shared_info_t *shared = current->shared_info;    
     net_ring_t *net_ring = current->net_ring_base;
-    unsigned int i;
+    unsigned int i, j;
     struct sk_buff *skb;
     tx_entry_t tx;
 
-    for ( i = net_ring->tx_cons; i != net_ring->tx_prod; i = TX_RING_INC(i) )
+    for ( j = 0; j < current->num_net_vifs; j++)
     {
-        if ( copy_from_user(&tx, net_ring->tx_ring+i, sizeof(tx)) )
-            continue;
+        net_ring = current->net_vif_list[j]->net_ring;
+        for ( i = net_ring->tx_cons; i != net_ring->tx_prod; i = TX_RING_INC(i) )
+        {
+            if ( copy_from_user(&tx, net_ring->tx_ring+i, sizeof(tx)) )
+                continue;
 
-        if ( TX_RING_INC(i) == net_ring->tx_event )
-            set_bit(_EVENT_NET_TX, &shared->events);
+            if ( TX_RING_INC(i) == net_ring->tx_event )
+                set_bit(_EVENT_NET_TX, &shared->events);
 
-        skb = alloc_skb(tx.size, GFP_KERNEL);
-        if ( skb == NULL ) continue;
-        skb_put(skb, tx.size);
-        if ( copy_from_user(skb->data, (void *)tx.addr, tx.size) )
-        {
-            kfree_skb(skb);
-            continue;
-        }
-        skb->dev = the_dev;
+            skb = alloc_skb(tx.size, GFP_KERNEL);
+            if ( skb == NULL ) continue;
+            skb_put(skb, tx.size);
+            if ( copy_from_user(skb->data, (void *)tx.addr, tx.size) )
+            {
+                kfree_skb(skb);
+                continue;
+            }
+            skb->dev = the_dev;
 
-        if ( skb->len < 16 )
-        {
-            kfree_skb(skb);
-            continue;
-        }
+            if ( skb->len < 16 )
+            {
+                kfree_skb(skb);
+                continue;
+            }
 
-        memcpy(skb->data + ETH_ALEN, skb->dev->dev_addr, ETH_ALEN);
+            memcpy(skb->data + ETH_ALEN, skb->dev->dev_addr, ETH_ALEN);
         
-        switch ( ntohs(*(unsigned short *)(skb->data + 12)) )
-        {
-        case ETH_P_ARP:
-            skb->protocol = __constant_htons(ETH_P_ARP);
-            if ( skb->len < 42 ) break;
-            memcpy(skb->data + 22, skb->dev->dev_addr, 6);
-            break;
-        case ETH_P_IP:
-            skb->protocol = __constant_htons(ETH_P_IP);
-            break;
-        default:
-            kfree_skb(skb);
-            skb = NULL;
-            break;
-        }
-
-        if ( skb != NULL )
-        {
-            skb_get(skb); /* get a reference for non-local delivery */
-            skb->protocol = eth_type_trans(skb, skb->dev);
-            if ( netif_rx(skb) == 0 )
+            switch ( ntohs(*(unsigned short *)(skb->data + 12)) )
             {
-                /* Give up non-local reference. Packet delivered locally. */
+            case ETH_P_ARP:
+                skb->protocol = __constant_htons(ETH_P_ARP);
+                if ( skb->len < 42 ) break;
+                memcpy(skb->data + 22, skb->dev->dev_addr, 6);
+                break;
+            case ETH_P_IP:
+                skb->protocol = __constant_htons(ETH_P_IP);
+                break;
+            default:
                 kfree_skb(skb);
+                skb = NULL;
+                break;
             }
-            else
+
+            if ( skb != NULL )
             {
-                /* Pass the non-local reference to the net device. */
-                skb_push(skb, skb->dev->hard_header_len);
-                dev_queue_xmit(skb);
+                skb_get(skb); /* get a reference for non-local delivery */
+                skb->protocol = eth_type_trans(skb, skb->dev);
+                if ( netif_rx(skb) == 0 )
+                {
+                    /* Give up non-local reference. Packet delivered locally. */
+                    kfree_skb(skb);
+                }
+                else
+                {
+                    /* Pass the non-local reference to the net device. */
+                    skb_push(skb, skb->dev->hard_header_len);
+                    dev_queue_xmit(skb);
+                }
             }
         }
+        net_ring->tx_cons = i;
     }
 
-    net_ring->tx_cons = i;
-
     return 0;
 }
 
index 38ba61772aa0657142ea1b348cfbffba1af27886..9030801f1423a12df2421e7d1325acaf1ffb5b71 100644 (file)
@@ -1,3 +1,3 @@
 O_TARGET := dom0.o
-obj-y := dom0_core.o
+obj-y := dom0_core.o vfr.o
 include $(TOPDIR)/Rules.make
diff --git a/xenolinux-2.4.16-sparse/arch/xeno/drivers/dom0/vfr.c b/xenolinux-2.4.16-sparse/arch/xeno/drivers/dom0/vfr.c
new file mode 100644 (file)
index 0000000..3f22282
--- /dev/null
@@ -0,0 +1,277 @@
+/******************************************************************************
+ * vfr.c
+ *
+ * Interface to the virtual firewall/router.
+ *
+ */
+
+#include <linux/config.h>
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/string.h>
+#include <linux/errno.h>
+#include <linux/proc_fs.h>
+
+#include <asm/hypervisor-ifs/network.h>
+
+static struct proc_dir_entry *proc_vfr;
+
+static unsigned char readbuf[1024];
+
+/* Helpers, implemented at the bottom. */
+u32 getipaddr(const char *buff, unsigned int len);
+u16 antous(const char *buff, int len);
+
+static int vfr_read_proc(char *page, char **start, off_t off,
+                                          int count, int *eof, void *data)
+{   
+    strcpy(page, readbuf);
+    *readbuf = '\0';
+    *eof = 1;
+    *start = page;
+    return strlen(page);
+}
+
+/* The format for the vfr interface is as follows:
+ *
+ *  COMMAND <field>=<val> [<field>=<val> [...]]
+ *
+ *  where:
+ *
+ *  COMMAND = { ACCEPT | COUNT }
+ *
+ *  field=val pairs are as follows:
+ *
+ *  field = { srcaddr | dstaddr }
+ *      val is a dot seperated, numeric IP address.
+ *
+ *  field = { srcport | dstport }
+ *      val is a (16-bit) unsigned int
+ *
+ *  field = { proto }
+ *      val = { IP | TCP | UDP | ARP }
+ *
+ */
+
+static int vfr_write_proc(struct file *file, const char *buffer,
+                                           u_long count, void *data)
+{
+  network_op_t op;
+  int ret, len;
+  int ts, te, tl; // token start, end, and length
+  int fs, fe, fl; // field.
+
+  len = count;
+  ts = te = 0;
+
+  memset(&op, 0, sizeof(network_op_t));
+
+  // get the command:
+  while ( count && (buffer[ts] == ' ') ) { ts++; count--; } // skip spaces.
+  te = ts;
+  while ( count && (buffer[te] != ' ') ) { te++; count--; } // command end
+  if ( te <= ts ) goto bad;
+  tl = te - ts;
+
+  if ( strncmp(&buffer[ts], "ADD", tl) == 0 )
+  {
+     op.cmd = NETWORK_OP_ADDRULE;
+  }
+  else if ( strncmp(&buffer[ts], "DELETE", tl) == 0 )
+  {
+     op.cmd = NETWORK_OP_DELETERULE;
+  }
+  else if ( strncmp(&buffer[ts], "PRINT", tl) == 0 )
+  {
+     op.cmd = NETWORK_OP_GETRULELIST;
+     goto doneparsing;
+  }
+        
+  ts = te;
+  
+  // get the action
+  while ( count && (buffer[ts] == ' ') ) { ts++; count--; } // skip spaces.
+  te = ts;
+  while ( count && (buffer[te] != ' ') ) { te++; count--; } // command end
+  if ( te <= ts ) goto bad;
+  tl = te - ts;
+
+  if ( strncmp(&buffer[ts], "ACCEPT", tl) == 0 ) 
+  {
+    op.u.net_rule.action = NETWORK_ACTION_ACCEPT;
+    goto keyval;
+  }
+  if ( strncmp(&buffer[ts], "COUNT", tl) == 0 ) 
+  {
+    op.u.net_rule.action = NETWORK_ACTION_COUNT;
+    goto keyval;
+  }
+   
+  // default case;
+  return (len);
+  
+
+  // get the key=val pairs.
+ keyval:
+  while (count)
+  {
+    //get field
+    ts = te; while ( count && (buffer[ts] == ' ') ) { ts++; count--; }
+    te = ts;
+    while ( count && (buffer[te] != ' ') && (buffer[te] != '=') ) 
+      { te++; count--; }
+    if ( te <= ts ) goto bad;
+    tl = te - ts;
+    fs = ts; fe = te; fl = tl; // save the field markers.
+    // skip "   =   " (ignores extra equals.)
+    while ( count && ((buffer[te] == ' ') || (buffer[te] == '=')) ) 
+      { te++; count--; }
+    ts = te;
+    while ( count && (buffer[te] != ' ') ) { te++; count--; }
+    tl = te - ts;
+
+    if ( (fl <= 0) || (tl <= 0) ) goto bad;
+
+    if (strncmp(&buffer[fs], "srcaddr", fl) == 0) 
+    {  
+      op.u.net_rule.src_addr = getipaddr(&buffer[ts], tl-1);
+    }
+    else if (strncmp(&buffer[fs], "dstaddr", fl) == 0)
+    {    
+      op.u.net_rule.dst_addr = getipaddr(&buffer[ts], tl-1);
+    }
+    else if (strncmp(&buffer[fs], "srcaddrmask", fl) == 0) 
+    {
+      op.u.net_rule.src_addr_mask = getipaddr(&buffer[ts], tl-1);
+    }
+    else if (strncmp(&buffer[fs], "dstaddrmask", fl) == 0)
+    {
+      op.u.net_rule.dst_addr_mask = getipaddr(&buffer[ts], tl-1);
+    }
+    else if (strncmp(&buffer[fs], "srcport", fl) == 0)
+    {
+      op.u.net_rule.src_port = antous(&buffer[ts], tl-1);
+    }
+    else if (strncmp(&buffer[fs], "dstport", fl) == 0)
+    {
+      op.u.net_rule.dst_port = antous(&buffer[ts], tl-1);
+    }
+    else if (strncmp(&buffer[fs], "srcportmask", fl) == 0)
+    {
+      op.u.net_rule.src_port_mask = antous(&buffer[ts], tl-1);
+    }
+    else if (strncmp(&buffer[fs], "dstportmask", fl) == 0)
+    {
+      op.u.net_rule.dst_port_mask = antous(&buffer[ts], tl-1);
+    }
+    else if (strncmp(&buffer[fs], "srcint", fl) == 0)
+    {
+      op.u.net_rule.src_interface = antous(&buffer[ts], tl-1);
+    }
+    else if (strncmp(&buffer[fs], "dstint", fl) == 0)
+    {
+      op.u.net_rule.dst_interface = antous(&buffer[ts], tl-1);
+    }
+    else if ( (strncmp(&buffer[fs], "proto", fl) == 0))
+    {
+      if (strncmp(&buffer[ts], "ip", tl))
+         op.u.net_rule.proto = NETWORK_PROTO_IP;
+      if (strncmp(&buffer[ts], "tcp", tl))
+         op.u.net_rule.proto = NETWORK_PROTO_TCP;
+      if (strncmp(&buffer[ts], "udp", tl))
+         op.u.net_rule.proto = NETWORK_PROTO_UDP;
+      if (strncmp(&buffer[ts], "arp", tl))
+         op.u.net_rule.proto = NETWORK_PROTO_ARP;
+      
+    }
+  }
+
+ doneparsing:  
+  ret = HYPERVISOR_network_op(&op);
+  return(len);
+
+ bad:
+  return(len);
+    
+    
+}
+
+static int __init init_module(void)
+{
+    *readbuf = '\0';
+    proc_vfr = create_proc_entry ("vfr", 0600, &proc_root);
+    if ( proc_vfr != NULL )
+    {
+        proc_vfr->owner      = THIS_MODULE;
+        proc_vfr->nlink      = 1;
+        proc_vfr->read_proc  = vfr_read_proc;
+        proc_vfr->write_proc = vfr_write_proc;
+        printk("Successfully installed virtual firewall/router interface\n");
+    }
+    return 0;
+}
+
+static void __exit cleanup_module(void)
+{
+    if ( proc_vfr == NULL ) return;
+    remove_proc_entry("vfr", &proc_root);
+    proc_vfr = NULL;
+}
+
+module_init(init_module);
+module_exit(cleanup_module);
+
+/* Helper functions start here: */
+
+u16 antous(const char *buff, int len)
+{
+  int ret;
+  char c;
+
+  ret = 0;
+
+  while ( (len) && ((c = *buff) >= '0') && (c <= '9') )
+  {
+    ret *= 10;
+    ret += c - '0';
+    buff++; len--;
+  }
+
+  return ret;
+}
+
+u32 getipaddr(const char *buff, unsigned int len)
+{
+  int i; 
+  char c;
+  u32 ret, val;
+
+  ret = 0; val = 0;
+
+  while ( len )
+  {
+    if (!((((c = *buff) >= '0') && ( c <= '9')) || ( c == '.' ) ) ) 
+    {
+      return(0); // malformed.
+    }
+
+    if ( c == '.' ) {
+      if (val > 255) return (0); //malformed.
+      ret = ret << 8; 
+      ret += val;
+      val = 0;
+      len--; buff++;
+      continue;
+    }
+    val *= 10;
+    val += c - '0';
+    buff++; len--;
+  }
+  ret = ret << 8;
+  ret += val;
+
+  return (ret);
+}
+
index c10bef0d4c37996eae20b01dca366465096028be..54cb99095a1b6922d17f4dd466de81c6da57c815 100644 (file)
@@ -51,43 +51,19 @@ typedef struct net_ring_st {
     unsigned int rx_ring_size;
 } net_ring_t;
 
-/* net_vif_st is the larger struct that describes a virtual network interface
- * it contains a pointer to the net_ring_t structure that needs to be on a 
- * shared page between the hypervisor and guest.  The vif struct is private 
- * to the hypervisor and is used primarily as a container to allow routing 
- * and interface administration.  This define should eventually be moved to 
- * a non-shared interface file, as it is of no relevance to the guest.
- */
-
-typedef struct net_vif_st {
-    net_ring_t  *net_ring;
-    int          id;
-    // rules table goes here in next revision.
-} net_vif_t;
-
-/* VIF-related defines. */
-#define MAX_GUEST_VIFS    2 // each VIF is a small overhead in task_struct
-#define MAX_SYSTEM_VIFS 256 // trying to avoid dynamic allocation 
-
-/* vif globals */
-extern int sys_vif_count;
-
-/* This is here for consideration:  Having a global lookup for vifs
- * may make the guest /proc stuff more straight forward, and could 
- * be used in the routing code.  I don't know if it warrants the 
- * overhead yet.
- */
-
-/* net_vif_t sys_vif_list[MAX_SYSTEM_VIFS]; */
-
 /* Specify base of per-domain array. Get returned free slot in the array. */
 net_ring_t *create_net_vif(int domain);
 
 /* Packet routing/filtering code follows:
  */
 
-#define NETWORK_ACTION_DROP 0
-#define NETWORK_ACTION_PASS 1
+#define NETWORK_ACTION_ACCEPT   0
+#define NETWORK_ACTION_COUNT    1
+
+#define NETWORK_PROTO_IP        0
+#define NETWORK_PROTO_TCP       1
+#define NETWORK_PROTO_UDP       2
+#define NETWORK_PROTO_ARP       3
 
 typedef struct net_rule_st 
 {
@@ -99,10 +75,11 @@ typedef struct net_rule_st
     u32  dst_addr_mask;
     u16  src_port_mask;
     u16  dst_port_mask;
-
-    int  src_interface;
-    int  dst_interface;
-    int  action;
+    u16  proto;
+    
+    u16  src_interface;
+    u16 dst_interface;
+    u16  action;
 } net_rule_t;
 
 /* Network trap operations and associated structure. 
@@ -112,6 +89,7 @@ typedef struct net_rule_st
 
 #define NETWORK_OP_ADDRULE      0
 #define NETWORK_OP_DELETERULE   1
+#define NETWORK_OP_GETRULELIST  2
 
 typedef struct network_op_st 
 {
@@ -122,7 +100,13 @@ typedef struct network_op_st
     }
     u;
 } network_op_t;
-    
+
+typedef struct net_rule_ent_st
+{
+    net_rule_t r;
+    struct net_rule_ent_st *next;
+} net_rule_ent_t;
+
 /* Drop a new rule down to the network tables. */
 int add_net_rule(net_rule_t *rule);